'---------------------------------------------------------------------------------------
' Module      : mLockedFiles
' DateTime    : 11/08/2009 02:10
' Author      : SqUeEzEr
' Mail        : scott_van_dinter@hotmail.com@hotmail.com
' Purpose     : Close filehandles owned by other processes
' Usage       : At your own risk
' Requirements: None
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce
'               or publish this code on any web site,
'               online service, or distribute as source
'               on any media without express permission.
'
' Reference   : Deleting locked files
'		http://www.codeguru.com/cpp/w-p/files/fileio/article.php/c1287
'
' History     : 11/08/2009 First Cut....................................................
'---------------------------------------------------------------------------------------
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function NtDuplicateObject Lib "NTDLL.DLL" (ByVal hSourceProcess As Long, ByVal hSourceHandle As Long, ByVal hCopyProcess As Long, CopyHandle As Long, ByVal DesiredAccess As Long, ByVal Attributes As Long, ByVal Options As Long) As Long
Private Declare Function NtClose Lib "NTDLL.DLL" (ByVal ObjectHandle As Long) As Long

Public Declare Function CreateToolhelp32Snapshot Lib "Kernel32.dll" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
Public Declare Function Process32First Lib "Kernel32.dll" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
Public Declare Function Process32Next Lib "Kernel32.dll" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
Public Declare Function CloseHandle Lib "Kernel32.dll" (ByVal hObject As Long) As Long
Public Declare Function OpenProcess Lib "Kernel32.dll" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
            
Public Declare Function RtlAdjustPrivilege Lib "ntdll" (ByVal Privilege As Long, ByVal Enable As Boolean, ByVal Client As Boolean, WasEnabled As Long) As Long

Public Type PROCESSENTRY32
    dwSize              As Long
    cntUsage            As Long
    th32ProcessID       As Long ' Identifier of the process
    th32DefaultHeapID   As Long
    th32ModuleID        As Long
    cntThreads          As Long
    th32ParentProcessID As Long
    pcPriClassBase      As Long
    dwFlags             As Long
    szExeFile           As String * 260
End Type

Private Const FILE_FLAG_BACKUP_SEMANTICS As Long = &H2000000
Private Const GENERIC_ALL As Long = &H10000000
Private Const FILE_SHARE_READ As Long = &H1&
Private Const FILE_SHARE_WRITE As Long = &H2&
Private Const OPEN_EXISTING As Long = 3&

Private Const DUPLICATE_CLOSE_SOURCE = &H1
Private Const PROCESS_ALL_ACCESS As Long = &H1F0FFF

Public Const TH32CS_SNAPPROCESS As Long = &H2

Public Function Closehandles(sFileName As String) As Boolean
Dim hFile       As Long
Dim pInfo       As PROCESSENTRY32
Dim hSnapshot   As Long
Dim lSuccess    As Long
Dim lRet        As Long
Dim hProcess    As Long

Call RtlAdjustPrivilege(20, True, True, 0)

hFile = CreateFile(sFileName, GENERIC_ALL, FILE_SHARE_WRITE And FILE_SHARE_READ, 0&, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0&)
    
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pInfo.dwSize = Len(pInfo)
lSuccess = Process32First(hSnapshot, pInfo)
    
    If hSnapshot = -1 Then
        Debug.Print "Unable to take snapshot of process list!"
    Else
        Do While lSuccess <> 0
            hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pInfo.th32ProcessID)
            Call NtDuplicateObject(hProcess, hFile, 0, ByVal 0, 0, 0, DUPLICATE_CLOSE_SOURCE)
            Call NtClose(hProcess)
            pInfo.dwSize = Len(pInfo)
            lSuccess = Process32Next(hSnapshot, pInfo)
        Loop
        lRet = CloseHandle(hSnapshot)
    End If
    Closehandles = True
End Function

If Closehandles("C:\file.txt") Then Kill "C:\file.txt"